package c15;

import java.util.concurrent.Callable;
import java.util.concurrent.locks.Lock;

/**
 * 异步操作
 */
public class MyExcutor {

    static class ExcutorThread<V> extends Thread {
        private boolean done = false;
        private Exception exception;
        private Object lock;
        private Callable<V> task;
        private V result;

        public ExcutorThread(Callable task, Object lock) {
            this.task = task;
            this.lock = lock;
        }

        @Override
        public void run() {
            try {
                result = task.call();
            } catch (Exception e) {
                exception = e;
                e.printStackTrace();
            } finally {
                synchronized (lock) {
                    done = true;
                    lock.notifyAll();
                }
            }
        }

        protected V getResult() {
            return result;
        }

        protected boolean isDone() {
            return done;
        }

        protected Exception getException() {
            return exception;
        }
    }

    public <V> MyFuture<V> execute(final Callable<V> task) {
        final Object lock = new Object();
        final ExcutorThread<V> thread = new ExcutorThread(task, lock);
        thread.start();
        return new MyFuture<V>() {
            @Override
            public V get() throws Exception {
                synchronized (lock) {
                    while(!thread.isDone()) {
                        lock.wait();
                    }
                }
                if (thread.getException() != null) {
                    throw thread.getException();
                }
                return thread.getResult();
            }
        };
    }

    public static void main(String[] args) throws Exception {
        MyExcutor pool = new MyExcutor();
        MyFuture<Integer> result = pool.execute(() -> {
            System.out.println("task working");
            Thread.sleep(3000);
            return 1024;
        });
        System.out.println("1 MB是多少个字节?");
        System.out.println(result.get());
    }
}

interface MyFuture<V> {
    V get() throws Exception;
}

